﻿namespace Atomic.Modules.Security
{
    using System;

    /// <summary>
    /// 账户信息。
    /// </summary>
    public class Account
    {
        /// <summary>
        /// 账号。
        /// </summary>
        private string _accountNumber = string.Empty;

        /// <summary>
        /// 密码。
        /// </summary>
        private string _password = string.Empty;

        /// <summary>
        /// 初始化账户信息。
        /// </summary>
        public Account()
        {
        }

        /// <summary>
        /// 初始化账户信息。
        /// </summary>
        /// <remarks>
        /// 初始化数据的同时验证数据是否合格，不合格则抛异常。
        /// 传入的密码是否是未加密状态则自动加密。
        /// </remarks>
        /// <param name="accountNumber">账号。</param>
        /// <param name="password">密码。</param>
        public Account(string accountNumber, string password)
        {
            this.AccountNumber = accountNumber;
            this.Password = password;
        }

        /// <summary>
        /// 账号。
        /// </summary>
        public string AccountNumber
        {
            get
            {
                return this._accountNumber;
            }
            set
            {
                string accountNumber = value;

                this.ValidateAccountNumber(accountNumber);

                this._accountNumber = accountNumber;
            }
        }

        /// <summary>
        /// 密码。
        /// </summary>
        /// <remarks>
        /// 这里保存的是已加密的密码。
        /// </remarks>
        public string Password
        {
            get
            {
                return this._password;
            }
            set
            {
                string password = value;

                //判断传入的密码是否加密，未加密则进行密码验证并加密。
                if (!this.IsEncrypt(password))
                {
                    this.ValidatePassword(password);

                    password = this.PasswordEncrypt(password);
                }

                this._password = password;
            }
        }

        /// <summary>
        /// 判断传入的密码是否与当前账户的密码一致。
        /// </summary>
        /// <param name="password">密码。</param>
        /// <returns>一致则返回 true，否则返回 flase。</returns>
        public bool EqualPassword(string password)
        {
            return this.Password == this.PasswordEncrypt(password);
        }

        /// <summary>
        /// 修改密码。
        /// </summary>
        /// <param name="password">密码。</param>
        public void ChangePassword(string password)
        {
            this.ValidatePassword(password);

            this.Password = this.PasswordEncrypt(password);
        }

        /// <summary>
        /// 给密码加密。
        /// </summary>
        /// <param name="password">密码。</param>
        /// <returns>加密后的密码。</returns>
        private string PasswordEncrypt(string password)
        {
            return UserValidator.Current.MD5(password);
        }

        /// <summary>
        /// 判断传入密码是否已加密。
        /// </summary>
        /// <param name="password">密码。</param>
        /// <returns>已加密则返回 true，否则返回 flase。</returns>
        private bool IsEncrypt(string password)
        {
            return !string.IsNullOrWhiteSpace(password) && password.Length == 32;
        }

        /// <summary>
        /// 验证账号是否合格。
        /// </summary>
        /// <param name="accountNumber">账号。</param>
        private void ValidateAccountNumber(string accountNumber)
        {
            if (string.IsNullOrWhiteSpace(accountNumber) || !UserValidator.Current.Range(accountNumber, 4, 20))
            {
                throw new ArgumentNullException("accountNumber", "账号的字符数必须在 4 - 20 个之间。");
            }

            if (!UserValidator.Current.AccountString(accountNumber))
            {
                throw new ArgumentException("accountNumber", "账号必须是数字、字母和下划线的组合。");
            }
        }

        /// <summary>
        /// 验证密码是否合格。
        /// </summary>
        /// <param name="password">密码。</param>
        private void ValidatePassword(string password)
        {
            if (string.IsNullOrWhiteSpace(password) || !UserValidator.Current.Range(password, 6, 20))
            {
                throw new ArgumentNullException("password", "密码的字符数必须在 6 - 20 个之间。");
            }

            if (!UserValidator.Current.AccountString(password))
            {
                throw new ArgumentException("password", "密码必须是数字、字母和下划线的组合。");
            }
        }
    }
}